home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / av.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  12KB  |  309 lines

  1. /*  $VER: vbcc (av.c) V0.4     */
  2. /*  aktive Variablen und Elimination unnoetiger Anweisungen */
  3.  
  4. #include "opt.h"
  5.  
  6. static char FILE_[]=__FILE__;
  7.  
  8. /*  fuer aktive Variablen   */
  9. struct Var **vilist;
  10. unsigned int vcount;    /*  0..vcount-rcount-1: vars, vcount-rcount..vcount: DREFOBJs */
  11. unsigned int rcount;
  12. size_t vsize;
  13. unsigned char *av_globals,*av_address,*av_statics,*av_drefs;
  14. int report_dead_statements;
  15.  
  16. void print_av(unsigned char *bitvector)
  17. /*  druckt Variablen in einem Bitvektor */
  18. {
  19.     int i;
  20.     if(!bitvector) {printf("active variables not available\n");return;}
  21.     for(i=0;i<vcount-rcount;i++)
  22.         if(BTST(bitvector,i)) printf("%3d: %s,%ld\n",i,vilist[i]->identifier,zl2l(vilist[i]->offset));
  23.     for(i=vcount-rcount;i<vcount;i++)
  24.         if(BTST(bitvector,i)) printf("%3d: (%s),%ld\n",i,vilist[i]->identifier,zl2l(vilist[i]->offset));
  25. }
  26. void num_vars(void)
  27. /*  Numeriert Variablen und erzeugt Indexliste  */
  28. {
  29.     unsigned int i,j;struct IC *p;struct Var *v,*a[3],*vp;
  30.     if(DEBUG&1024) printf("numerating variables loop1\n");
  31.     /*  alle Indizes auf -1 */
  32.     a[0]=vl1;
  33.     a[1]=vl2;
  34.     a[2]=vl3;
  35.     for(j=0;j<3;j++){
  36.         v=a[j];
  37.         while(v){
  38.             v->index=-1;
  39.             /*  Variablen von inline-Funktionen */
  40.             if(j==0&&v->fi&&v->fi->first_ic){
  41.                 for(vp=v->fi->vars;vp;vp=vp->next) vp->index=-1;
  42.             }
  43.             v=v->next;
  44.         }
  45.     }
  46.     /*  erst alle Variablen, die als DREFOBJ benutzt werden */
  47.     if(DEBUG&1024) printf("numerating variables loop2\n");
  48.     i=0;
  49.     for(p=first_ic;p;p=p->next){
  50.         if(p->code<LABEL||p->code>BRA){
  51.             int c=p->code;
  52.             j=p->typf&NQ;
  53.             if(c==SUBPFP) j=POINTER;
  54.             if(c==ADDI2P||c==SUBIFP) j=POINTER;
  55.             if(c==CONVCHAR||c==CONVUCHAR) j=CHAR;
  56.             if(c==CONVSHORT||c==CONVUSHORT) j=SHORT;
  57.             if(c==CONVINT||c==CONVUINT) j=INT;
  58.             if(c==CONVLONG||c==CONVULONG) j=LONG;
  59.             if(c==CONVPOINTER) j=POINTER;
  60.             if(c==CONVFLOAT) j=FLOAT;
  61.             if(c==CONVDOUBLE) j=DOUBLE;
  62.             if((p->q1.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
  63.                 v=p->q1.v;
  64.                 if(!v->vtyp->next||(v->vtyp->next->flags&NQ)!=j) v->flags|=DNOTTYPESAFE;
  65.                 if(v->index<0) v->index=i++;
  66.             }
  67.             j=p->typf&NQ;
  68.             if(c==SUBPFP) j=POINTER;
  69.             if((p->q2.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
  70.                 v=p->q2.v;
  71.                 if(!v->vtyp->next||(v->vtyp->next->flags&NQ)!=j) v->flags|=DNOTTYPESAFE;
  72.                 if(v->index<0) v->index=i++;
  73.             }
  74.             j=p->typf&NQ;
  75.             if(c==ADDI2P||c==SUBIFP) j=POINTER;
  76.             if((p->z.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)){
  77.                 v=p->z.v;
  78.                 if(!v->vtyp->next||(v->vtyp->next->flags&NQ)!=j) v->flags|=DNOTTYPESAFE;
  79.                 if(v->index<0) v->index=i++;
  80.             }
  81.         }
  82.     }
  83.     if(DEBUG&1024) printf("numerating variables loop3\n");
  84.     rcount=i;    /*  Anzahl der DREFOBJ-Variablen    */
  85.     /*  jetzt den Rest  */
  86.     for(p=first_ic;p;p=p->next){
  87.         if(1/*p->code<LABEL||p->code>BRA*/){
  88.             j=p->typf&NQ;
  89.             if((p->q1.flags&(VAR|DREFOBJ))==VAR){
  90.                 v=p->q1.v;
  91.                 if((v->vtyp->flags&NQ)!=j) v->flags|=NOTTYPESAFE;
  92.                 if(v->index<0) v->index=i++;
  93.             }
  94.             if((p->q2.flags&(VAR|DREFOBJ))==VAR){
  95.                 v=p->q2.v;
  96.                 if((v->vtyp->flags&NQ)!=j) v->flags|=NOTTYPESAFE;
  97.                 if(v->index<0) v->index=i++;
  98.             }
  99.             if((p->z.flags&(VAR|DREFOBJ))==VAR){
  100.                 v=p->z.v;
  101.                 if((v->vtyp->flags&NQ)!=j) v->flags|=NOTTYPESAFE;
  102.                 if(v->index<0) v->index=i++;
  103.             }
  104.         }
  105.     }
  106.     if(DEBUG&1024) printf("numerating variables loop4\n");
  107.     vcount=i+rcount; /*  alle benutzten Variablen+Anzahl der DREFOBJs    */
  108.     vilist=mymalloc(vcount*sizeof(struct Var *));
  109.     for(j=0;j<3;j++){
  110.         int i;
  111.         v=a[j];
  112.         while(v){
  113.             i=v->index;
  114. /*            printf("%s has index %d\n",v->identifier,i);*/
  115.             if(i>=0){
  116.                 if(i>=vcount-rcount) ierror(0);
  117.                 vilist[i]=v;
  118.                 if(i<rcount) vilist[i+vcount-rcount]=v;
  119.             }
  120.             /*  Variablen von inline-Funktionen */
  121.             if(j==0&&v->fi&&v->fi->first_ic){
  122.                 for(vp=v->fi->vars;vp;vp=vp->next){
  123.                     i=vp->index;
  124.                     if(i>=0){
  125.                         if(i>=vcount-rcount) ierror(0);
  126.                         vilist[i]=vp;
  127.                         if(i<rcount) vilist[i+vcount-rcount]=vp;
  128.                     }
  129.                 }
  130.             }
  131.             v=v->next;
  132.         }
  133.     }
  134.  
  135.     vsize=(vcount+CHAR_BIT-1)/CHAR_BIT;
  136.     if(DEBUG&1024) printf("%lu variables (%lu DREFOBJs), vsize=%lu\n",(unsigned long)vcount,(unsigned long)rcount,(unsigned long)vsize);
  137.  
  138.     av_drefs=mymalloc(vsize);
  139.     memset(av_drefs,0,vsize);
  140.     /*  alle DREFOBJs   */
  141.     for(i=vcount-rcount;i<vcount;i++) BSET(av_drefs,i);
  142.  
  143.     /*  av_globals enthaelt alle globalen Variablen und av_address      */
  144.     /*  zusaetzlich noch alle Variablen, deren Adressen genommen wurden */
  145.     av_globals=mymalloc(vsize);
  146.     memset(av_globals,0,vsize);
  147.     av_statics=mymalloc(vsize);
  148.     memset(av_statics,0,vsize);
  149.     av_address=mymalloc(vsize);
  150.     memcpy(av_address,av_globals,vsize);
  151.     for(i=0;i<vcount-rcount;i++){
  152.         if(vilist[i]->nesting==0||vilist[i]->storage_class==EXTERN) BSET(av_globals,i);
  153.         if(vilist[i]->flags&USEDASADR) BSET(av_address,i);
  154.         if(vilist[i]->storage_class==STATIC) BSET(av_statics,i);
  155.         if(i<rcount){
  156. /*            if((vilist[i]->vtyp->flags&NQ)!=POINTER){ printf("%s(%ld)\n",vilist[i]->identifier,zl2l(vilist[i]->offset));ierror(0);}*/
  157.             BSET(av_address,i+vcount-rcount);
  158.             BSET(av_globals,i+vcount-rcount);
  159.         }
  160.     }
  161. }
  162. void print_vi(void)
  163. /*  Druckt vilist und testet Konsistenz */
  164. {
  165.     int i;
  166.     printf("\nprint_vi()\n");
  167.     for(i=0;i<vcount;i++){
  168.         if(!vilist[i]||(i<rcount&&vilist[i]->index!=i)) ierror(0);
  169.         printf("%3d: %s\n",i,vilist[i]->identifier);
  170.     }
  171. }
  172. void av_change(struct IC *p,unsigned char *use,unsigned char *def)
  173. /*  Berechnet die Aenderungen, die sich durch IC p an use und def ergeben.  */
  174. {
  175.     int i,j,n=-1;
  176.     int g1,g2;
  177.  
  178.     /*  Wenn eine Quelle==Ziel, dann wird dadurch kein neuer use erzeugt,   */
  179.     /*  um z.B. unbenutzte Induktionsvariablen in Schleifen zu eliminieren. */
  180.     g1=compare_objs(&p->q1,&p->z,p->typf);
  181.     g2=compare_objs(&p->q2,&p->z,p->typf);
  182.     if(!g1&&(p->q1.flags&(VAR|DREFOBJ))==VAR) n=p->q1.v->index;
  183.     if(!g2&&(p->q2.flags&(VAR|DREFOBJ))==VAR) n=p->q2.v->index;
  184.  
  185.     for(j=0;j<p->use_cnt;j++){
  186.         i=p->use_list[j].v->index;
  187.         if(p->use_list[j].flags&DREFOBJ) i+=vcount-rcount;
  188.         if(i>=vcount) continue;
  189.         if(i!=n&&!BTST(def,i)) BSET(use,i);
  190.     }
  191.  
  192.     /*  Ein Wert wird nicht zerstoert, wenn es kein elementarer Typ ist und */
  193.     /*  die Groesse kleiner als die Variable (steht in alle solchen ICs in  */
  194.     /*  q2.val.vlong.                                                       */
  195.     if((p->z.flags&(VAR|DREFOBJ))==VAR&&g1&&g2&&((p->z.v->vtyp->flags&NQ)<=POINTER||zleqto(p->q2.val.vlong,szof(p->z.v->vtyp)))){
  196.         i=p->z.v->index;
  197.         if(i>=vcount) ierror(0);
  198.         if(!BTST(use,i)) BSET(def,i);
  199.         /*  Wenn p geaendert wird, wird auch *p geaendert   */
  200.         if(i<rcount&&!BTST(def,i+vcount-rcount)) BSET(use,i+vcount-rcount);
  201.     }
  202.     if((p->z.flags&(VAR|DREFOBJ))==(VAR|DREFOBJ)&&g1&&g2){
  203.         i=p->z.v->index+vcount-rcount;
  204.         if(i>=vcount) ierror(0);
  205.         if(!BTST(use,i)) BSET(def,i);
  206.     }
  207. }
  208. void active_vars(struct flowgraph *fg)
  209. /*  analysiert aktive Variablen im Flussgraphen, nomain==0, wenn zu     */
  210. /*  optimierende Funktion main() ist                                    */
  211. {
  212.     struct IC *p;
  213.     int changed,pass;struct flowgraph *g;
  214.  
  215.     if(DEBUG&1024){printf("analysing active variables\n");/*scanf("%d",&i);*/}
  216.     tmp=mymalloc(vsize);
  217.     /*  av_gen und av_kill fuer jeden Basic Block berechnen */
  218.     if(DEBUG&1024){printf("active_vars(): loop1\n");/*scanf("%d",&i);*/}
  219.     g=fg;
  220.     while(g){
  221.         g->av_gen=mymalloc(vsize);
  222.         memset(g->av_gen,0,vsize);
  223.         g->av_kill=mymalloc(vsize);
  224.         memset(g->av_kill,0,vsize);
  225.         g->av_in=mymalloc(vsize);
  226.         memset(g->av_in,0,vsize);
  227.         g->av_out=mymalloc(vsize);
  228.         memset(g->av_out,0,vsize);
  229.         for(p=g->start;p;p=p->next){
  230.             av_change(p,g->av_gen,g->av_kill);
  231.             if(p==g->end) break;
  232.         }
  233.         g=g->normalout;
  234.     }
  235.  
  236.     /*  av_in und av_out fuer alle Bloecke berechnen    */
  237.     if(DEBUG&1024){printf("active_vars(): loop2\npass: ");/*scanf("%d",&i);*/}
  238.     pass=0;
  239.     do{
  240.         if(DEBUG&1024) {printf(" %d",++pass);fflush(stdout);}
  241.         changed=0;
  242.         g=fg;
  243.         while(g){
  244.             /* out(B)=U in(C) ueber alle Nachfolger C von B */
  245.             memset(g->av_out,0,vsize);  /*  noetig? */
  246.             if(g->branchout) bvunite(g->av_out,g->branchout->av_in,vsize);
  247.             if((!g->end||g->end->code!=BRA)&&g->normalout) bvunite(g->av_out,g->normalout->av_in,vsize);
  248.             /*  Am Ende muessen alle globalen Variablen bekannt sein    */
  249.             if(!g->normalout){
  250.                 bvunite(g->av_out,av_globals,vsize);
  251.                 /*if(!nocall)*/ bvunite(g->av_out,av_statics,vsize);
  252.             }
  253.             /* in(B)=use(B)U(out(B)-def(B)) */
  254.             memcpy(tmp,g->av_out,vsize);
  255.             bvdiff(tmp,g->av_kill,vsize);
  256.             bvunite(tmp,g->av_gen,vsize);
  257.  
  258.             if(!bvcmp(tmp,g->av_in,vsize)){changed=1;memcpy(g->av_in,tmp,vsize);}
  259.             g=g->normalout;
  260.         }
  261.     }while(changed);
  262.     if(DEBUG&1024) printf("\n");
  263.     free(tmp);
  264. }
  265. int dead_assignments(struct flowgraph *fg)
  266. /*  Findet Zuweisungen, die unnoetig sind, da die Variable nie mehr     */
  267. /*  benutzt werden kann.                                                */
  268. {
  269.     int changed=0;struct IC *p;unsigned char *isused;
  270.     int i,j;
  271.     if(DEBUG&1024) printf("searching for dead assignments\n");
  272.     isused=mymalloc(vsize);
  273.     while(fg){
  274.         memcpy(isused,fg->av_out,vsize);
  275.         p=fg->end;
  276.         while(p){
  277.             if(p->z.flags&VAR){
  278.                 i=p->z.v->index;
  279.                 if(p->z.flags&DREFOBJ) i+=vcount-rcount;
  280.                 if(!BTST(isused,i)&&!(p->typf&VOLATILE)){
  281.                     if(DEBUG&1024){printf("dead assignment deleted:\n");pric2(stdout,p);}
  282.                     if(*p->z.v->identifier&&p->code!=ASSIGN){ err_ic=p;error(170,i>=vcount-rcount?"*":"",p->z.v->identifier);err_ic=0;}
  283.                     if(p->code!=GETRETURN) changed=1;
  284.                     if(p==fg->start){remove_IC_fg(fg,p);break;}
  285.                     p=p->prev;remove_IC_fg(fg,p->next);
  286.                     continue;
  287.                 }
  288.                 if((p->z.v->vtyp->flags&NQ)<=POINTER||zleqto(p->q2.val.vlong,szof(p->z.v->vtyp)))
  289.                     BCLR(isused,i);
  290.                 /*  bei Zuweisung an p wird *p aktiv    */
  291.                 if(i<rcount) BSET(isused,i+vcount-rcount);
  292.             }
  293.             for(j=0;j<p->use_cnt;j++){
  294.                 i=p->use_list[j].v->index;
  295.                 if(p->use_list[j].flags&DREFOBJ) i+=vcount-rcount;
  296.                 if(i>=vcount) continue;
  297.                 BSET(isused,i);
  298.             }
  299.  
  300.             if(p==fg->start) break;
  301.             p=p->prev;
  302.         }
  303.         fg=fg->normalout;
  304.     }
  305.     free(isused);
  306.     return(changed);
  307. }
  308.  
  309.